var IFRAME_ID = 0;

document.write('<script language="JavaScript" src="' + MEDIA_URL + 'js/jquery.treeview.js"></script>');

var plugins = new Object();
document.write('<script language="JavaScript" src="' + MEDIA_URL + 'js/plugin_img.js"></script>');

function render() {
  document.getElementById('page_body').innerHTML = wikify(document.getElementById('page_text').value);
  $('.treeview').treeview();
  if(document.getElementById('iframe_id')) {
    var h = document.body.scrollHeight + 31;
    parent.document.getElementById(document.getElementById('iframe_id').innerHTML).style.height = h + 'px';
  }
}


function wikify(str) {
  str = str.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
  var l, r, m;
  var s = 0;

  while(1) {
    if(-1 == (l = str.indexOf('{{{', s))) {
      return wikify2(str);
    }
    if(-1 == (r = str.indexOf('}}}', l + 3))) {
      return wikify2(str);
    }
    m = str.substring((l + 3), r);
    if(m.match(/\n/)) {
      if(l > 0 && "\n" == str.charAt(l - 1)) {
        return wikify2(str.substring(0, l)) + "\n" + m + wikify(str.substring(r + 3));
      }
      else {
        return wikify2(str.substring(0, l)) + m + wikify(str.substring(r + 3));
      }
    }
    s = r + 3;
  }
}


function wikify2(str) {
  var out = new Array();
  var lines = str.split("\n");
  if("\n" == str.charAt(str.length - 1)) {
    lines.pop();
  }

  for(var i = 0; i < lines.length; i++) {
    line = lines[i];
    if(line.match(/^\-\-\-\-$/)) {
      out.push('<hr />');
      continue;
    }
    if(line.match(/^\*\*\*\*\*\*/)) {
      out.push('<h6>' + subWikify(rtrim(line.substring(6))) + '</h6>');
      continue;
    }
    if(line.match(/^\*\*\*\*\*/)) {
      out.push('<h5>' + subWikify(rtrim(line.substring(5))) + '</h5>');
      continue;
    }
    if(line.match(/^\*\*\*\*/)) {
      out.push('<h4>' + subWikify(rtrim(line.substring(4))) + '</h4>');
      continue;
    }
    if(line.match(/^\*\*\*/)) {
      out.push('<h3>' + subWikify(rtrim(line.substring(3))) + '</h3>');
      continue;
    }
    if(line.match(/^\*\*/)) {
      out.push('<h2>' + subWikify(rtrim(line.substring(2))) + '</h2>');
      continue;
    }
    if(line.match(/^\*/)) {
      out.push('<h1>' + subWikify(rtrim(line.substring(1))) + '</h1>');
      continue;
    }

    var c;
    if(c = line.match(/^[\-#]/)) {
      var li = new Array();
      li.push(line);
      while(1) {
        if(i < lines.length - 1 && lines[i + 1].charAt(0) == c) {
          i++;
          li.push(lines[i]);
        }
        else {
          break;
        }
      }
      out.push(makeList(li));
      continue;
    }

    if(line.match(/^\|/)) {
      var tbl = new Array();
      tbl.push(line);
      while(1) {
        if(i < lines.length -1 && lines[i + 1].match(/^\|/)) {
          i++;
          tbl.push(lines[i]);
        }
        else {
          break;
        }
      }
      out.push(makeTable(tbl));
      continue;
    }

    if(line.match(/^>/)) {
      var bq = new Array();
      bq.push(line);
      while(1) {
        if(i < lines.length - 1 && lines[i + 1].match(/^>/)) {
          i++;
          bq.push(lines[i]);
        }
        else {
          break;
        }
      }
      out.push(makeBlockQuote(bq));
      continue;
    }

    if(line.match(/^ /)) {
      var cb = new Array();
      cb.push(line);
      while(1) {
        if(i < lines.length - 1 && lines[i + 1].match(/^ /)) {
          i++;
          cb.push(lines[i]);
        }
        else {
          break;
        }
      }
      out.push(makeCodeBlock(cb));
      continue;
    }

    if(line.match(/^\+/)) {
      var tv = new Array();
      tv.push(line);
      while(1) {
        if(i < lines.length - 1 && lines[i + 1].match(/^\+/)) {
          i++;
          tv.push(lines[i]);
        }
        else {
          break;
        }
      }
      out.push(makeTreeView(tv));
      continue;
    }

    if(lines.length - 1 == i || (lines[i + 1].match(/^[\-\+\|\*> #]/) && lines[i] != '')) {
      out.push(subWikify(line));
    }
    else {
      out.push(subWikify(line) + '<br />');
    }
  }
  return out.join("\n");
}


function subWikify(str) {
  var l, r;
  if(-1 < (l = str.indexOf('{{{', 0)) && -1 < (r = str.indexOf('}}}', l + 3))) {
    return subWikify2(str.substring(0, l)) + str.substring(l + 3, r) + subWikify(str.substring(r + 3));
  }
  else {
    return subWikify2(str);
  }
}

function subWikify2(str) {
  var l, r;

  var re = new RegExp(/([^\[]*)\[([^\[]+)\[([^\]]+)\]\](.*)/);
  var w = re.exec(str);
  if(w) {
    for(var key in plugins) {
      if(w[2] == key) {
        return subWikify2(w[1]) + plugins[key](w[3]) + subWikify2(w[4]);
      }
    }
  }

  if(str.match(/.*\[include\[.+\]\].*/)) {
    var w = /(.*)\[include\[(.+)\]\](.*)/.exec(str);
    var id = 'iframe_' + IFRAME_ID;
    return subWikify2(w[1]) + '<iframe src="' + IFRAME_VIEW_URL + w[2] + '/' + id + '/" id="' + id + '" style="border:none;display:block;width:100%;margin:0px;padding:0px;overflow:hidden" frameborder="0" cellspacing="0"></iframe>' + subWikify2(w[3]);
  }

  if(-1 < (l = str.indexOf('==', 0)) && -1 < (r = str.indexOf('==', l + 2))) {
    return subWikify2(str.substring(0, l)) + '<span style="text-decoration:line-through">' + subWikify2(str.substring(l + 2, r)) + '</span>' + subWikify2(str.substring(r + 2));
  }

  if(-1 < (l = str.indexOf("''", 0)) && -1 < (r = str.indexOf("''", l + 2))) {
    return subWikify2(str.substring(0, l)) + '<span style="font-weight:bold">' + subWikify2(str.substring(l + 2, r)) + '</span>' + subWikify2(str.substring(r + 2));
  }

  if(-1 < (l = str.indexOf('%%', 0)) && -1 < (r = str.indexOf('%%', l + 2))) {
    return subWikify2(str.substring(0, l)) + '<span style="font-style:italic">' + subWikify2(str.substring(l + 2, r)) + '</span>' + subWikify2(str.substring(r + 2));
  }

  if(-1 < (l = str.indexOf('__', 0)) && -1 < (r = str.indexOf('__', l + 2))) {
    return subWikify2(str.substring(0, l)) + '<span style="text-decoration:underline">' + subWikify2(str.substring(l + 2, r)) + '</span>' + subWikify2(str.substring(r + 2));
  }

  else if(-1 < (l = str.indexOf('[[', 0)) && -1 < (r = str.indexOf(']]', l + 2))) {
    return subWikify2(str.substring(0, l)) + makeLink(str.substring(l + 2, r)) + subWikify2(str.substring(r + 2));
  }

  else if(-1 < (l = str.indexOf('<', 0)) && str.charAt(l + 1).match(/\S/) && -1 < (r = str.indexOf('>', l + 2))) {
    return subWikify2(str.substring(0, l)) + '&lt;' + subWikify2(str.substring(l + 1, r)) + '&gt;' + subWikify2(str.substring(r + 1));
  }

  else if(-1 < (l = str.indexOf('\\\\', 0))) {
    return subWikify2(str.substring(0, l)) + '\\' + subWikify2(str.substring(l + 2));
  }

  else if(-1 < (l = str.indexOf('\\n', 0))) {
    return subWikify2(str.substring(0, l)) + '<br />' + subWikify2(str.substring(l + 2));
  }

  else {
    return str;
  }
}


function makeList(lines) {

  var out = new Array();
  var types = new Array(); // ul: 1, ol: 2
  var currentType, currentLevel, list;
  var previousLevel = 0;
  var buf = '';

  while(str = lines.shift()) {
    if(str.match(/^([\-#]+)/)) {
      currentLevel = RegExp.$1.length;
      list = str.substring(currentLevel);
    }

    if(currentLevel < previousLevel) {
        out.push(buf + '</li>');
        for(var i = 0; i < previousLevel - currentLevel; i++) {
          if(types.pop() == 1) {
            out.push('</ul></li>');
          }
          else {
            out.push('</ol></li>');
          }
        }
    }

    else if(currentLevel == previousLevel) {
      out.push(buf + '</li>');
    }

    else {
      if(buf != '') {
        out.push(buf);
      }
      for(var i = previousLevel; i < currentLevel; i++) {
        if('-' == RegExp.$1.charAt(i)) {
          out.push('<ul>');
          types.push(1);
        }
        else {
          out.push('<ol>');
          types.push(2);
        }
      }
    }
    buf = '<li>' + subWikify(list);
    previousLevel = currentLevel;
  }
  out.push(buf + '</li>');
  for(var i = 1; i < previousLevel; i++) {
    if(types.pop() == 1) {
      out.push('</li></ul>');
    }
    else {
      out.push('</li></ol>');
    }
  }
  if(types.pop() == 1) {
    out.push('</ul>');
  }
  else {
    out.push('</ol>');
  }
  return out.join("\n");
}


function makeBlockQuote(lines) {

  var out = new Array();
  var currentLevel, quote;
  var previousLevel = 0;
  var p = false;

  while(str = lines.shift()) {
    if(str.match(/^(>+)/)) {
      currentLevel = RegExp.$1.length;
      quote = str.substring(currentLevel);
    }

    if(currentLevel < previousLevel) {
      out.push('</p>');
      for(var i = 0; i < previousLevel - currentLevel; i++) {
        out.push('</blockquote>');
      }
      out.push('<p class="wiki">');
      out.push(subWikify(quote));
    }

    else if(currentLevel == previousLevel) {
      out.push('<br />' + subWikify(quote));
    }

    else {
      if(p) {
        out.push('</p>');
      }
      for(var i = 0; i < currentLevel - previousLevel; i++) {
        out.push('<blockquote class="wiki">');
      }
      out.push('<p class="wiki">');
      p = true;
      out.push(subWikify(quote));
    }
    previousLevel = currentLevel;
  }

  out.push('</p>');
  for(var i = 0; i < previousLevel; i++) {
    out.push('</blockquote>');
  }

  return out.join("\n");
}


function makeCodeBlock(lines) {
  var out = new Array();
  out.push('<pre class="code">');
  while(str = lines.shift()) {
    out.push(subWikify(str.substr(1)));
  }
  out.push('</pre>');
  return out.join("\n");
}


function makeTreeView(lines) {
  var out = new Array();
  var currentLevel, list;
  var previousLevel = 0;
  var buf = '';

  while(str = lines.shift()) {
    if(str.match(/^(\++)/)) {
      currentLevel = RegExp.$1.length;
      list = str.substring(currentLevel);
    }

    if(currentLevel < previousLevel) {
      out.push(buf + '</li>');
      for(var i = 0; i < previousLevel - currentLevel; i++) {
        out.push('</ul></li>');
      }
    }

    else if(currentLevel == previousLevel) {
      out.push(buf + '</li>');
    }

    else if(0 == previousLevel) {
      out.push('<ul class="treeview">');
    }

    else {
      out.push(buf);
      for(var i = previousLevel; i < currentLevel; i++) {
        out.push('<ul>');
      }
    }

    buf = '<li>' + subWikify(list);
    previousLevel = currentLevel;
  }
  out.push(buf + '</li>');
  for(var i = 1; i < previousLevel; i++) {
    out.push('</li></ul>');
  }
  out.push('</ul>');
  return out.join("\n");
}


function makeLink(str) {
  var i = str.indexOf("|", 0);
  if(-1 == i) {
    if(isUri(str)) {
      return '<a href="' + str + '" target="_blank">' + str + '</a>';
    }
    else {
      str = escape_title(str);
      return '<a href="' + VIEW_URL + str + '">' + str + '</a>';
    }
  }
  else {
    return '<a href="' + str.substring(i + 1) + '" target="_blank">' + str.substring(0, i) + '</a>';
  }
}


function escape_title(str) {
  return str.replace(/\"/g, '&quot;');
}


function makeTable(lines) {
  var out = new Array();
  var w, rowType, align, cell, lines2;
  var colCount, colSpan, cs, rowSpan, colType;

  out.push('<table class="wiki">');

  while(str = lines.shift()) {
    w = /^\|(.*)\|c$/.exec(str);
    if(null != w) {
      out.push('<caption>' + w[1] + '</caption>');
      continue;
    }

    if(str.match(/\|h$/)) {
      rowType = 'h';
      str = str.substring(1, str.length - 1);
    }
    else {
      rowType = 'd';
      str = str.substring(1);
    }

    out.push('<tr class="wiki">');
    colCount = -1;
    colSpan = 1;
    while(1) {
      colCount++;
      w = /^([^\|]*)\|(.*)$/.exec(str);
      if(null == w ) break;
      cell = ltrim(rtrim(w[1]));;
      str = w[2];
      if('>' == cell) {
        colSpan++;
        continue;
      }

      if('~' == cell) {
        continue;
      }

      if(cell.match(/^!/)) {
        cell = cell.substring(1);
        colType = 'h';
      }
      else {
        colType = 'd';
      }

//      cell = subWikify2(cell);

      if(w[1].match(/^\s.*\s$/)) {
        align = ' align="center"';
      }
      else if(w[1].match(/^\s/)) {
        align = ' align="right"';
      }
      else {
        align = '';
      }

      if(1 < colSpan) {
        cs = ' colspan="' + colSpan + '"';
      }
      else {
        cs = '';
      }

      lines2 = lines.clone();
      rowSpan = getRowSpan(lines2, colCount);
      if(1 < rowSpan) {
        rs = ' rowspan="' + rowSpan + '"';
      }
      else {
        rs = '';
      }

      if(rowType == 'h' || colType == 'h') {
        out.push('<th' + rs + cs + align + ' class="wiki">' + subWikify(cell) + '</th>');
      }
      else {
        out.push('<td' + rs + cs + align + ' class="wiki">' + subWikify(cell) + '</td>');
      }
      colSpan = 1;
    }
    out.push('</tr>');
  }
  out.push('</table>');
  return out.join("\n");
}

function getRowSpan(lines, colCount) {
  var str, i, cell;
  var rs = 1;
  while(str = lines.shift()) {
    str = str.substring(1);
    for(i = -1; i < colCount; i++) {
      w = /^([^\|]*)\|(.*)$/.exec(str);
      if(null == w) return rs;
      cell = ltrim(rtrim(w[1]));
      str = w[2];
    }
    if('~' == cell) {
      rs++;
      continue;
    }
    else {
      return rs;
    }
  }
  return rs;
}

Array.prototype.clone = function() {
    return Array.apply(null,this)
}


function rtrim(str) {
  var rep = /(\s)*$/g;
  return str.replace(rep, '');
}


function ltrim(str) {
  var rep = /^(\s)*/g;
  return str.replace(rep, '');
}


function isUri(str) {
  if(str.match(/^(https?|ftp):\/\/.+$/)) {
    return true;
  }
  return false;
}

